﻿#include "httpserver.h"
#include "httpdefine.h"
#include "fzspdlog.h"
#include <winsock2.h>
#include <thread>
#include <functional>

int getThreadId() {
    return static_cast<int>(std::hash<std::thread::id>()(std::this_thread::get_id()));
}

CHttpServerMgr* CHttpServerMgr::instance=nullptr;
QMutex CHttpServerMgr::m_mutex;
CHttpServerMgr* CHttpServerMgr::GetInstance(int listenPort)
{
    if(!instance)
    {
        if(m_mutex.tryLock(5000))
        {
            if(!instance)
            {
                instance = new (std::nothrow) CHttpServerMgr(listenPort);
            }
            m_mutex.unlock();
        }
    }
    return instance;
}

int CHttpServerMgr::Start()
{
    // [FDD-2025-03-021] 使用成员变量 m_listenThread，不使用 detach
    m_listenThread = std::thread([this]() {
        ListenThreadFunc();
    });
    // 不调用 detach()，保留线程句柄以便后续 join

    return 0;
}

int CHttpServerMgr::Stop()
{
    for (auto& httpServer : m_httpServerPool)
    {
        httpServer->Stop();
    }
    return 0;
}

/**
 * @brief [FDD-2025-03-021][API-006] 正确关闭HTTP服务
 * 设置标志、关闭 listen socket 并等待所有线程 join
 * @return 成功 join 的线程数
 */
int CHttpServerMgr::Shutdown()
{
    XLOG_INFO("[HTTP Shutdown] Starting shutdown process...");

    // 1. 设置停止标志
    m_shouldStop.store(true);
    m_isRunning.store(false);

    // 2. 停止所有 HTTP 服务器
    for (auto& httpServer : m_httpServerPool)
    {
        if (httpServer) {
            httpServer->Stop();
        }
    }

    // 3. 关闭监听 socket，中断 accept 调用
    if (m_listenSocket != INVALID_SOCKET) {
        closesocket(m_listenSocket);
        m_listenSocket = INVALID_SOCKET;
        XLOG_INFO("[HTTP Shutdown] Listen socket closed");
    }

    int joinedThreads = 0;

    // 4. 等待所有工作线程 join（5秒超时）
    for (auto& thread : m_workerThreads) {
        if (thread.joinable()) {
            // 简单实现：直接 join（可能阻塞）
            // 生产环境应使用 timed_join 或条件变量
            thread.join();
            joinedThreads++;
            XLOG_INFO("[HTTP Shutdown] Worker thread joined, total: {}", joinedThreads);
        }
    }
    m_workerThreads.clear();

    // 5. 等待监听线程 join
    if (m_listenThread.joinable()) {
        m_listenThread.join();
        joinedThreads++;
        XLOG_INFO("[HTTP Shutdown] Listen thread joined");
    }

    // 6. 清空服务器池
    m_httpServerPool.clear();

    XLOG_INFO("[HTTP Shutdown] Shutdown complete, total threads joined: {}", joinedThreads);
    return joinedThreads;
}

CHttpServerMgr::CHttpServerMgr(int listenPort)
    : m_isRunning(false),
    m_shouldStop(false),
    m_listenPort(listenPort),
    m_listenSocket(INVALID_SOCKET)
{
#ifdef WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
}
CHttpServerMgr::~CHttpServerMgr()
{
#ifdef WIN32
    WSACleanup();
#endif
}

void CHttpServerMgr::ListenThreadFunc()
{
    XLOG_INFO("http server listen thread id :{}",getThreadId());
    //创建监听套接字，并开启监听
    int result = BindSocket(m_listenPort, SOMAXCONN);
    if (0 != result)
    {
        XLOG_ERROR("HTTP服务监听套接字创建失败，端口:{}",m_listenPort);
        return;
    }
    XLOG_INFO("HTTP服务监听端口:{}", m_listenPort);
    //线程池数量：CPU核数 x 2
    int threadPoolSize = std::thread::hardware_concurrency() * 2;
    for (int i = 0; i < threadPoolSize; i++)
    {
        CHttpServerPtr httpServer(new CHttpServer(m_listenSocket));
        httpServer->Start();
        m_httpServerPool.push_back(httpServer);
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int CHttpServerMgr::BindSocket(int port, int backlog)
{
    //创建监听套接字
    m_listenSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (m_listenSocket == INVALID_SOCKET)
    {
        XLOG_ERROR("create listen socket failed.");
        return -1;
    }

    //地址可复用
    int result = 0, optval = 1;
    result = setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int));

    //设为非阻塞模式
    int block = 1;
    result = ::ioctlsocket(m_listenSocket, FIONBIO, (u_long FAR*) & block);
    if (SOCKET_ERROR == result)
    {
        XLOG_ERROR("ioctlsocket failed :{}", WSAGetLastError());
        closesocket(m_listenSocket);
        m_listenSocket = INVALID_SOCKET;
        return -1;
    }

    struct sockaddr_in local_addr;
    memset(&local_addr, 0, sizeof(struct sockaddr_in));
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(port);
    local_addr.sin_addr.s_addr = INADDR_ANY;

    //绑定IP地址和端口
    if (INVALID_SOCKET == ::bind(m_listenSocket, (struct sockaddr*)&local_addr, sizeof(struct sockaddr)))
    {
        XLOG_ERROR("bind failed :{}",WSAGetLastError());
        closesocket(m_listenSocket);
        m_listenSocket = INVALID_SOCKET;
        return -1;
    }

    //开启监听
    result = listen(m_listenSocket, backlog);
    if (result < 0)
    {
        XLOG_ERROR("listen failed : {}", WSAGetLastError());
        closesocket(m_listenSocket);
        m_listenSocket = INVALID_SOCKET;
        return -1;
    }
    return 0;
}

CHttpServer::CHttpServer(const int& listenSocket)
    :m_base(nullptr)
    ,m_http(nullptr)
    ,m_listenSocket(listenSocket)
{
    //m_handle = nullptr;
}

CHttpServer::~CHttpServer()
{
    Stop();
}

/**
 * @brief [FDD-2025-03-021] 发送 HTTP 应答，使用局部变量和 unique_ptr 管理 evbuffer
 * @param pstReq HTTP 请求对象
 * @param code HTTP 状态码
 * @param reason 状态描述
 * @param response 响应内容
 * @return 0 成功，-1 失败
 */
int CHttpServer::SendReply(struct evhttp_request* pstReq, int code, const char* reason, const std::string& response)
{
    if (!pstReq) {
        XLOG_ERROR("[SendReply] Invalid request pointer");
        return -1;
    }

    // 使用 unique_ptr 自动管理 evbuffer，确保异常安全
    struct evbuffer* evb = evbuffer_new();
    if (!evb) {
        XLOG_ERROR("[SendReply] Failed to create evbuffer");
        return -1;
    }

    // 自定义 deleter
    auto evbuffer_deleter = [](struct evbuffer* buf) {
        if (buf) {
            evbuffer_free(buf);
        }
    };
    std::unique_ptr<struct evbuffer, decltype(evbuffer_deleter)> evb_guard(evb, evbuffer_deleter);

    // 返回HTTP头部
    evhttp_add_header(pstReq->output_headers, "Server", "HttpServer");
    evhttp_add_header(pstReq->output_headers, "Content-Type", "application/json;charset=utf-8");
    evhttp_add_header(pstReq->output_headers, "Connection", "keep-alive");
    evhttp_add_header(pstReq->output_headers, "Cache-Control", "no-cache");
    evhttp_add_header(pstReq->output_headers, "Access-Control-Allow-Origin", "*");
    evhttp_add_header(pstReq->output_headers, "Access-Control-Allow-Credentials", "true");
    evhttp_add_header(pstReq->output_headers, "Access-Control-Allow-Methods", "*");
    evhttp_add_header(pstReq->output_headers, "Access - Control - Allow - Headers", "Origin,X-Requested-With, Content-Type, Accept");
    evhttp_add_header(pstReq->output_headers, "Content-Length", std::to_string(response.size()).c_str());

    evbuffer_add(evb, response.data(), response.size());

    // 发送应答
    evhttp_send_reply(pstReq, code, reason, evb);

    // evb_guard 会自动释放 evbuffer
    return 0;
}

// [FDD-2025-03-021] 使用 thread_local 替代静态变量，避免竞态
thread_local std::string t_response;

int CHttpServer::rspHttp(const char* const rspStr)
{
    // [FDD-2025-03-021] 保留以维持兼容性，使用 thread_local 存储响应
    if (strcmp(rspStr, "") == 0) {
        return false;
    }
    t_response = rspStr;
    return true;
}

std::string CHttpServer::getThreadLocalResponse()
{
    std::string response = t_response;
    t_response.clear();  // 读取后清空
    return response;
}

int CHttpServer::Start()
{
    //初始化HTTP请求消息映射表
    struct HTTPReqInfo* cmd = httpReqInfo;
    int index = 0;
    for (; cmd->cmdKey != NULL; cmd++)
    {
        struct HTTPReqInfoMap cmdMap;
        cmdMap.index = index;
        cmdMap.cmd = cmd;
        m_httpReqMap[cmd->cmdKey] = cmdMap;
        index++;
    }

    //启动http服务工作线程
    m_thread = std::move(std::thread([this]() {
        WorkThread();
        }));
    m_thread.detach();
    return 0;
}

int CHttpServer::Stop()
{
    if (m_base)
    {
        event_base_loopbreak(m_base);
        event_base_free(m_base);
        m_base = nullptr;
    }
    return 0;
}

void CHttpServer::WorkThread()
{
    XLOG_INFO("http server work thread id :{}",getThreadId());
    //创建event base对象
    m_base = event_base_new();
    if (!m_base)
    {
        XLOG_ERROR("create event base failed.");
        return;
    }
    //创建http server
    m_http = evhttp_new(m_base);
    if (!m_http)
    {
        XLOG_ERROR("create evhttp failed.");
        goto err;
    }

    //接收新的连接请求
    if (0 != evhttp_accept_socket(m_http, m_listenSocket))
    {
        XLOG_ERROR("evhttp accecpt failed.");
        goto err;
    }

    //设置HTTP请求超时处理时间，60秒
    evhttp_set_timeout(m_http, 60);

    //设置HTTP支持的请求类型
    evhttp_set_allowed_methods(m_http, EVHTTP_REQ_GET | EVHTTP_REQ_OPTIONS | EVHTTP_REQ_POST);

    //设置http请求回调函数
    evhttp_set_gencb(m_http, HttpReqCallback, this);

    XLOG_INFO("http server started.");
    //进入事件循环
    event_base_dispatch(m_base);

err:
    //销毁和释放http server资源
    if (m_http)
        evhttp_free(m_http);

    //销毁和释放event base资源
    if (m_base)
        event_base_free(m_base);
}

void CHttpServer::HttpReqCallback(struct evhttp_request* pstReq, void* userData)
{
    XLOG_INFO("HttpReqCallback thread id :{}",getThreadId());
    evhttp_cmd_type cmdType = evhttp_request_get_command(pstReq);
    if (EVHTTP_REQ_GET == cmdType || EVHTTP_REQ_POST == cmdType)
    {
        CHttpServer* this_ = (CHttpServer*)userData;
        if (!this_)
        {
            XLOG_ERROR("get this failed.");
            evhttp_send_error(pstReq, HTTP_BADREQUEST, "Bad Request");
            return;
        }
        //URI中包含？的，用于数据请求；否则用于文件请求
        const char* uri = evhttp_request_get_uri(pstReq);
        if (!strstr(uri, "?"))
            this_->OnRequestData(pstReq);
        else
            this_->OnRequestFile(pstReq);
    }
    else
    {
        XLOG_ERROR("not support request.");
        evhttp_send_error(pstReq, HTTP_BADREQUEST, "Bad Request");
    }
}



void CHttpServer::OnRequestUpFile(evhttp_request* req, void* arg)
{
}

void CHttpServer::OnRequestFile(evhttp_request* pstReq)
{
    //TODO:文件下载逻辑代码

}

void CHttpServer::OnRequestData(struct evhttp_request* pstReq)
{
    if (nullptr == pstReq)
    {
        XLOG_ERROR("invalid parameter.");
        return;
    }

    evhttp_cmd_type cmdType = evhttp_request_get_command(pstReq);
    if (EVHTTP_REQ_GET == cmdType) //GET请求
    {
        RequestProcessGet(pstReq);
    }
    else if (EVHTTP_REQ_POST == cmdType) //POST请求
    {
        RequestProcessPost(pstReq);
    }
    else
    {
        XLOG_ERROR("not support method.");
        std::string errorResp = HTTP_RESPOND_MESSAGES[1];
        SendReply(pstReq, HTTP_BADMETHOD, "NOT-SUPPORT-METHOD", errorResp);
    }
}

void CHttpServer::RequestProcessGet(evhttp_request* pstReq)
{
    //TODO：系统各种业务的GET请求
    //获取请求URI
    evhttp_cmd_type cmdType = EVHTTP_REQ_GET;
    const char* puri = evhttp_request_get_uri(pstReq);

    struct evkeyvalq headers;
    if (evhttp_parse_query(puri, &headers) != 0)
    {
        XLOG_ERROR("http bad request.");
        evhttp_send_error(pstReq, HTTP_BADREQUEST, 0);
        return;
    }

    //获取请求方法
    const char* cmd = evhttp_find_header(&headers, "terminal");
    if (cmd == NULL)
    {
        XLOG_ERROR("http bad request.");
        evhttp_send_error(pstReq, HTTP_BADREQUEST, 0);
        return;
    }
    //获取http请求负载数据
    std::string jsonData(std::move(GetContentFromRequest(pstReq)));
    XLOG_INFO("获取http请求负载数据:{}", jsonData);
    //http请求消息分发
    if (m_httpReqMap.count(cmd) > 0)
    {
        struct HTTPReqInfo* cmdFound = m_httpReqMap.at(cmd).cmd;
        if (cmdFound && cmdFound->called_fun)
        {
            std::string suri(puri);
            XLOG_INFO("POST request uri:{} \n msg body:{}", suri, jsonData);
            //触发回调
            cmdFound->called_fun(pstReq, jsonData, this);
            // [FDD-2025-03-021] 从 thread_local 获取响应
            std::string response = getThreadLocalResponse();
            SendReply(pstReq, HTTP_OK, "HTTP/1.1 OK", response);
        }
        else
        {
            XLOG_INFO("invalid http request cmd : {}", cmd);
            std::string errorResp = HTTP_RESPOND_MESSAGES[1];
            SendReply(pstReq, HTTP_BADMETHOD, "bad method", errorResp);
        }
    }
    else
    {
        // 使用默认响应
        std::string defaultResp = HTTP_RESPOND_MESSAGES[4];
        SendReply(pstReq, HTTP_OK, "HTTP/1.1 OK", defaultResp);
    }
}

std::string CHttpServer::GetContentFromRequest(struct evhttp_request* req)
{
    std::string data;
    struct evbuffer* buf = evhttp_request_get_input_buffer(req);
    while (evbuffer_get_length(buf))
    {
        int n;
        char cbuf[256];
        memset(cbuf, 0, sizeof(cbuf));
        n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
        if (n > 0)
        {
            data.append(cbuf, n);
        }
    }
    return data;
}

void CHttpServer::RequestProcessPost(evhttp_request* pstReq)
{
    //获取请求URI
    evhttp_cmd_type cmdType = EVHTTP_REQ_POST;
    const char* puri = evhttp_request_get_uri(pstReq);
    struct evhttp_uri* decoded = NULL;
    struct evkeyvalq headers;
    if (evhttp_parse_query(puri, &headers) != 0)
    {
        XLOG_ERROR("http bad request.");
        evhttp_send_error(pstReq, HTTP_BADREQUEST, 0);
        return;
    }
    decoded = evhttp_uri_parse(puri);
    //获取请求方法
    string path=evhttp_uri_get_path(decoded);
    int pos = path.find("/terminal/");
    if (pos < 0)
    {
        XLOG_ERROR("http bad request.");
        evhttp_send_error(pstReq, HTTP_BADREQUEST, 0);
        return;
    }
    //const char* cmd = evhttp_find_header(&headers, "Action");
    //if (cmd == NULL)
    //{
    //	XLOG_ERROR("http bad request.");
    //	evhttp_send_error(pstReq, HTTP_BADREQUEST, 0);
    //	return;
    //}
    //获取http请求负载数据
    std::string jsonData(std::move(GetContentFromRequest(pstReq)));
    XLOG_INFO("获取http请求负载数据:{}",jsonData);
    //http请求消息分发
    if (m_httpReqMap.count(path) > 0)
    {
        struct HTTPReqInfo* cmdFound = m_httpReqMap.at(path).cmd;
        if (cmdFound && cmdFound->called_fun)
        {
            std::string suri(puri);
            XLOG_INFO("POST request uri:{} \n msg body:{}",suri,jsonData);
            //触发回调
            cmdFound->called_fun(pstReq, jsonData, this);
            // [FDD-2025-03-021] 从 thread_local 获取响应
            std::string response = getThreadLocalResponse();
            SendReply(pstReq, HTTP_OK, "HTTP/1.1 200 OK", response);
        }
        else
        {
            XLOG_INFO("invalid http request cmd : {}", path);
            std::string errorResp = HTTP_RESPOND_MESSAGES[1];
            SendReply(pstReq, HTTP_BADMETHOD, "bad method", errorResp);
        }
    }
    else
    {
        std::string defaultResp = HTTP_RESPOND_MESSAGES[4];
        SendReply(pstReq, HTTP_OK, "HTTP/1.1 200 OK", defaultResp);
    }
}

int CHttpServer::Login(const struct evhttp_request* pstReq, const string& data, void* param)
{
    std::cout << "recv login request..." << std::endl;
    //TODO：登录

    XLOG_INFO("data:{}", data);
    XLOG_INFO("param:{}", (char*)param);
    rspHttp(data.c_str());
    string tempRsp = data;
    return 1;
}

int CHttpServer::Logout(const struct evhttp_request* pstReq, const string& data, void* param)
{
    std::cout << "recv logout request..." << std::endl;
    //TODO：登出
    return -1;
}

int CHttpServer::Heartbeat(const struct evhttp_request* pstReq, const string& data, void* param)
{
    std::cout << "recv hreatbeat request..." << std::endl;
    //TODO：心跳
    return -1;
}

